
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;

const PERMS_FILE      = 0644;
const PERMS_DIRECTORY = 0755;

const MODE_RDONLY   = 0x01;
const MODE_WRONLY   = 0x02;
const MODE_CREATE   = 0x08;
const MODE_APPEND   = 0x10;
const MODE_TRUNCATE = 0x20;

var nsSuperfishUtilsConstants = {
	// Superfish
//	extensionName: "superfish.com",
//	settingsPrefix: "Superfish",
//	extensionFullName: "superfish@superfish.com",
//	isEnabledByDefault: true
	
	// IeTab
	extensionName: "ip.cn",
	settingsPrefix: "IeTab",
	extensionFullName: "ietab@ip.cn",
	isEnabledByDefault: false
//	isEnabledByDefault: true
	
}



Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");


var sfLogger = {
		write: function(string){
//		    var gConsole = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
//		    dump("*** " + string + "\n");
//		    if (gConsole) {
//		      gConsole.logStringMessage(string);
//		    }
		}
}


////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////

var superfishSupportedSitesManager = {
	_SupportedSitesData: null,
	_aUtils: null,
	_isInitialize: false,
        _intervalWhenFail: 0,
	init: function(){
       		sfLogger.write("superfishSupportedSitesManager init ################## VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV++++++++++++++ 1");
       		if (!this._isInitialize && superfishSupportedSitesManager.getAUtils().isPluginStateEnabled()){
       			sfLogger.write("init VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV++++++++++++++ 2");
       			this._isInitialize = true;
                        try {
                            superfishSupportedSitesManager._SupportedSitesData = JSON.parse(superfishSupportedSitesManager.getAUtils().LoadStringFromFile(this.getFileFullName()));
                        }catch (ex) {
 	       		   sfLogger.write("superfishSupportedSitesManager init FAIL FFFFFFFFFFFFFf");
                           superfishSupportedSitesManager.onFail();
                        }
			if (superfishSupportedSitesManager._SupportedSitesData == null || this.isOldData()){
				this.updateSuppotedSitesDataOnceADay();
			}
       			sfLogger.write("superfishSupportedSitesManager init VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV++++++++++++++ 3");
       		} 
       		sfLogger.write("superfishSupportedSitesManager init end VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV++++++++++++++ 4");
	},
	getSuppotedSitesData: function(){
       		sfLogger.write("getSuppotedSitesData VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV++++++++++++++ 1");
       		if (superfishSupportedSitesManager._SupportedSitesData == null) {
	       		sfLogger.write("getSuppotedSitesData $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV++++++++++++++ 2");
                        try {
                            superfishSupportedSitesManager._SupportedSitesData = JSON.parse(superfishSupportedSitesManager.getAUtils().LoadStringFromFile(this.getFileFullName()));
                        } catch (ex) {
 	       		   sfLogger.write("getSuppotedSitesData FAIL FFFFFFFFFFFFFf");
                           superfishSupportedSitesManager._SupportedSitesData = "{}";
                        }
	       		sfLogger.write("getSuppotedSitesData $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV++++++++++++++ 3 superfishSupportedSitesManager._SupportedSitesData="+superfishSupportedSitesManager._SupportedSitesData);
       		} else if (this.isOldData()){
	       		sfLogger.write("getSuppotedSitesData EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV++++++++++++++ 4 ");
			this.updateSuppotedSitesDataOnceADay();
       		}
		return superfishSupportedSitesManager._SupportedSitesData;
	},
	updateSuppotedSitesDataOnceADay: function(){
       		sfLogger.write(" updateSuppotedSitesDataOnceADay ()()()()()()()()()()()()()()()()()VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV++++++++++++++ 1");

                var url = superfishSupportedSitesManager.getAUtils().getPluginDomain() + "getSupportedSitesJSON.action?callback="; // was: "callback=SF_isURISupported=", but this cause not well formed JSON
                sfLogger.write("updateSuppotedSitesDataOnceADay VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV++++++++++++++ 2");
                superfishSupportedSitesManager.getAUtils().sendASyncGetHTTPRequest(url,
                                                         false,
                                                         superfishSupportedSitesManager.getSupportedSitesOK,
                                                         superfishSupportedSitesManager.getSupportedSitesFail);
                sfLogger.write("updateSuppotedSitesDataOnceADay VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV++++++++++++++ 3");
                    
	},
	getIntervalWhenFail: function(){
       		sfLogger.write("getIntervalWhenFail 1   superfishSupportedSitesManager._intervalWhenFail="+superfishSupportedSitesManager._intervalWhenFail);
                switch (this._intervalWhenFail){ // 1 Second
                    case 0:
                        superfishSupportedSitesManager._intervalWhenFail = 3000;// 3 Second
                        break;
                    case 3000:
                        superfishSupportedSitesManager._intervalWhenFail = 10000;// 10 Second
                        break;
                    case 10000:
                        superfishSupportedSitesManager._intervalWhenFail = 60000; // 1 Minute
                        break;
                    case 60000:
                        superfishSupportedSitesManager._intervalWhenFail = 360000; // 6 Minutes
                        break;
                      case 360000:
                        superfishSupportedSitesManager._intervalWhenFail = 900000; //15 Minutes
                        break;
                     default:
                        superfishSupportedSitesManager._intervalWhenFail = 3600000;; // 1 hour
                }
       		sfLogger.write("getIntervalWhenFail  2  superfishSupportedSitesManager._intervalWhenFail="+superfishSupportedSitesManager._intervalWhenFail);
              return this._intervalWhenFail;
        },
	getSupportedSitesOK: function(_this,aEvent) {
       		sfLogger.write("getSupportedSitesOK <><><><><><><><><><><><><><><><><><><><>VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV++++++++++++++ 1");
        	var request = aEvent.target;
        	var jsonString = request.responseText;

       		sfLogger.write("getSupportedSitesOK VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV++++++++++++++ 2 jsonString="+jsonString);
                try {
                    superfishSupportedSitesManager._SupportedSitesData = JSON.parse(jsonString); //eval('(' + jsonString + ')'); //
                    try {
                        superfishSupportedSitesManager.getAUtils().saveStringToFile(jsonString, superfishSupportedSitesManager.getFileFullName());
                        superfishSupportedSitesManager._intervalWhenFail = 0;
                    } catch (ex) {
                                            sfLogger.write("EXCEPTION !!!!!!! getSupportedSitesOK  save to file catch ex= "+ ex);
                    }
                } catch (ex) {
                          		sfLogger.write("EXCEPTION !!!!!!! getSupportedSitesOK parse catch ex= "+ ex);
                                        superfishSupportedSitesManager.onFail();
                }



       		sfLogger.write("getSupportedSitesOK VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV++++++++++++++ 2 ");
	},
	getSupportedSitesFail: function() {
       		sfLogger.write("getSupportedSitesFail VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV++++++++++++++ 1");
               superfishSupportedSitesManager.onFail();
	},
        onFail: function(){
    	  sfLogger.write("superfishSupportedSitesManager    onFail");
          superfishSupportedSitesManager.setTimeout(superfishSupportedSitesManager.updateSuppotedSitesDataOnceADay,
                                                                                                                                                  superfishSupportedSitesManager.getIntervalWhenFail());
         },
          setTimeout: function (func, delay)
          {
                        sfLogger.write("superfishSupportedSitesManager::setTimeout ");
                        var timer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
                        var callback = { that: this,
                                                              notify: function () {
                                                                                                              func.call(this.that);
                                                                                                          }
                                                           };
                        timer.initWithCallback(callback,  delay,  Components.interfaces.nsITimer.TYPE_ONE_SHOT);
                        return timer;
        },
 	getFileFullName: function(){
		return this.getAUtils().getNameWithPathToProfileDirectory("SuportedSitesData.json");
	},
	isOldData: function(){
		return superfishSupportedSitesManager._SupportedSitesData && superfishSupportedSitesManager._SupportedSitesData.dataDate && superfishSupportedSitesManager._SupportedSitesData.dataDate < this.getAUtils().getStringDate(new Date());
	},
	getAUtils: function(){
		if (this._aUtils == null){
			this._aUtils = Components.classes['@'  + nsSuperfishUtilsConstants.extensionName +  '/nsSuperfishUtils;1'].getService().wrappedJSObject;
		} 
		return this._aUtils;
	}
}

//////////////////////////////////////////////////


var superfishCongratulationPageOpener = {
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// ******* Congratulation Page Opener *********
	// --------------------------------------------
	// We should open the congratulation page after the installation of the xpi.
	// Currently if the user installs then uninstalls and then installs it again we show the page only in the first time.
	// After the installation the user restart the firefox and the session is restored.
	// If on of the tabs in the restored session is a superfish domain, we show the congratulation page in this tab,
	// else we open a new tab.
	//
	// We make sure that we show the page only once, if we are not sure we prefer not to show it at all.
	//
	// Implementation:
	// In order to know if one of the tabs is a superfish domain we have to wait till the session is restored,
	// and till the URL in each tab is restored, so we have to roads that we wait till both of them complete.
	//   1) The "sessionstore-windows-restored" event. This object is an observer (implement observe),
	//   which is activated in nsSuperfishUtils.initialize().
	//   2) The "load" event which is also activated in nsSuperfishUtils.initialize() and then activated a "pageshow" event.
	// We keep the state of the events in flags.
	//
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////
	_isStillAboutBlank: true,
	_isSessionRestored: false,
	_aUtils: null,
	OnLoad: function() {
    	sfLogger.write("OnLoad LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL 1 ");
	    var win = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow('navigator:browser');
	    win.addEventListener("pageshow", function() {  superfishCongratulationPageOpener.OnPageShow();  }, false);
    	sfLogger.write("OnLoad LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL 2 ");
	},
	OnDOMNodeInsertedIntoDocument: function(){
		
	    sfLogger.write("OnDOMNodeInsertedIntoDocument ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1");
	    var win = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow('navigator:browser');
	    var element = win.document.getElementById("sfiframesync");
    	sfLogger.write("OnDOMNodeInsertedIntoDocument ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2 element="+element);
	    if (element != null) {
	    	sfLogger.write("OnDOMNodeInsertedIntoDocument ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 3 element="+element);
	    	element.addEventListener("DOMAttrModified", superfishCongratulationPageOpener.OnDOMAttrModified, false);
	    	sfLogger.write("OnDOMNodeInsertedIntoDocument ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4");
	    }
    	sfLogger.write("OnDOMNodeInsertedIntoDocument ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 5");
	},
	OnDOMAttrModified: function(event){
		sfLogger.write("----------------------------------------------------- +++++++++++++++++++++ attrName=" + event.attrName);
		if (event.attrName == 'saveItemRequest'){
			sfLogger.write("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA attrName=" + event.attrName +
					" ,event.target.id=" + event.target.id +
					" ,event.attrName=" + event.attrName +
					" ,event.prevValue=" + event.prevValue + 
					" ,event.newValue=" + event.newValue + 
					" ,event.attrChange=" + event.attrChange + 
					" ,event.relatedNode=" + event.relatedNode);
		}
	},
	OnPageShow : function() {
	    sfLogger.write("OnPageShow 1 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this._isStillAboutBlank="+this._isStillAboutBlank);
		if(this._isStillAboutBlank){
	    	sfLogger.write("OnPageShow 2 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 0");
			  var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator);
			  var browserEnumerator = wm.getEnumerator("navigator:browser");
			  var tab = null;
			  // Check each browser instance for our URL
			  while (browserEnumerator.hasMoreElements() && this._isStillAboutBlank) {
	    			sfLogger.write("OnPageShow 3 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 0");
				    var browserInstance = browserEnumerator.getNext().getBrowser();
				    // Check each tab of this browser instance
		    		var numTabs = browserInstance.tabContainer.childNodes.length;
		    		for(var index=0; index<numTabs && this._isStillAboutBlank; index++) {
		    			var currentBrowser = browserInstance.getBrowserAtIndex(index);
			      		if (currentBrowser.currentURI.spec != "about:blank") {
	    					sfLogger.write("OnPageShow 777 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 0");
			      			this._isStillAboutBlank = false;
			      			this.OpenCongratulationPage();
			      		}
		    		}
			  }
		} else {
//	    	sfLogger.write("OnPageShow 5 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 0");
//			this.OpenCongratulationPage();
	    }
	    sfLogger.write("OnPageShow ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1");
	    var win = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow('navigator:browser');
//	    win.addEventListener("DOMNodeInsertedIntoDocument", function() {superfishCongratulationPageOpener.OnDOMNodeInsertedIntoDocument(); }, false);
//	    sfLogger.write("OnPageShow ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1 3");
//	    sfLogger.write("OnPageShow ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1 5 content="+content);
//	    
//	    var element = content.document.getElementById("sfiframesync");
//	    sfLogger.write("OnPageShow ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2 element="+element);
	},
//	observe: function(subject, topic, data){
//	    switch(topic) {
//	    	case "sessionstore-windows-restored":
//	    		sfLogger.write("sessionstore-windows-restored 1 MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM");
//	    		this._isSessionRestored = true;
//	    		this.OpenCongratulationPage();
//	    		break;
//	    }
//	}, 
	OpenCongratulationPage: function(){
	    sfLogger.write("OpenCongratulationPage 1 YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY this._isSessionRestored="+this._isSessionRestored+" ,!this._isStillAboutBlank="+!this._isStillAboutBlank+" , this.isInitialized()="+this.isInitialized() + " ,!this.isCongratulationPageDone()="+!this.isCongratulationPageDone());
		// This function can be invoked many times per session start (because events may occur many times).
		// It it also being invoked any time a seesion start (not only after installation).
		// The first condition ensure that it will run only once. 
	    //if (nsSuperfishUtilsConstants.settingsPrefix != "IeTab" && this._isSessionRestored && !this._isStillAboutBlank && this.isInitialized() && !this.isCongratulationPageDone()) {
	    if (nsSuperfishUtilsConstants.settingsPrefix != "IeTab" && !this._isStillAboutBlank && this.isInitialized() && !this.isCongratulationPageDone()) {
		    sfLogger.write("OpenCongratulationPage 2 YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY ");
	    	try {
	    		if (this.isSetAndVeritySettingCongratulationDone()) {
	    			sfLogger.write("OpenCongratulationPage 3 YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY ");

	    			var windows = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(Components.interfaces.nsIWindowMediator).getEnumerator('navigator:browser');
	    	        var superfishSitefound = false;
	    	        while(!superfishSitefound && windows.hasMoreElements()){
	    				sfLogger.write("OpenCongratulationPage 4 YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY ");
	    	        	var win = windows.getNext();
	    	        	var tabbrowser = win.getBrowser();
	    	        	var numTabs = tabbrowser.browsers.length;
				
	                	for(var index=0; index<numTabs && !superfishSitefound; index++){
	    					sfLogger.write("OpenCongratulationPage 5 YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY ");
	                	 	var currentBrowser = tabbrowser.getBrowserAtIndex(index);
	                        var content = currentBrowser.contentWindow;
	                        var location = content.location;
	                        if (location != "about:blank") {
	    						sfLogger.write("OpenCongratulationPage 6 YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY ");
	                        	var host = location.hostname;
		                        var site = this.GetSuperFishSite();
	                    		if (site.toLowerCase().indexOf(host.toLowerCase()) >= 0) {
	    							sfLogger.write("OpenCongratulationPage 7 YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY ");
			                    	superfishSitefound = true;
			                        // The URL is already opened. Select this tab.
			                        tabbrowser.selectedTab = tabbrowser.mTabs[index];
			                        // Focus *this* browser-window
			                        win.focus();
			                        currentBrowser.contentWindow.location=this.GetSuperFishSite()+'congratulation.jsp?dlsource=' + this.GetDlSource();
	                    		}
	                        }
	                	}
	            	}
	
	    	        if(!superfishSitefound){
	    				sfLogger.write("OpenCongratulationPage 8 YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY ");
	                	var win = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow('navigator:browser');
	                	win.openUILinkIn(this.GetSuperFishSite()  + 'congratulation.jsp?dlsource=' + this.GetDlSource(), 'tab');
	             	}
	    		}
	        }
	        catch(ex)
	        {
	        	sfLogger.write("^^^^^^^^^^^^^^^^^^^^^^^^^^^^ superfishCongratulationPageOpener.OpenCongratulationPage() : catch: ex=" + ex);
	        }
	    }
	},
	isSetAndVeritySettingCongratulationDone: function(){
		// Returns true if the congratulation setting is successfully changed.
		this.setSetting("congratulationPageStatus","DONE");
		if (this.getSetting("congratulationPageStatus") == "DONE"){
			return true;
		} else {
			return false;
		}
	},
	isCongratulationPageDone: function(){
		return (this.getSetting("congratulationPageStatus") == "DONE");
	},
	getAUtils: function(){
		if (this._aUtils == null){
			this._aUtils = Components.classes['@'  + nsSuperfishUtilsConstants.extensionName +  '/nsSuperfishUtils;1'].getService().wrappedJSObject;
		} 
		return this._aUtils;
	},
	isInitialized: function(){
	    return this.getAUtils().isInitialized();
	},
	getSetting: function(name){
	    return this.getAUtils().getSetting(name);
	},
	setSetting: function(name,value){
	    return this.getAUtils().setSetting(name,value);
	},
	GetSuperFishSite : function() {
	    return this.getAUtils().getSiteDomain();
	},
	GetDlSource : function() {
	    return this.getAUtils().getDlsource();
	}
};

function nsSuperfishUtils() {

sfLogger.write("nsSuperfishUtils()"); 
this.wrappedJSObject = this;

}

nsSuperfishUtils.prototype = {
    classDescription: "Superfish Utils XPCOM Component",
    classID:          Components.ID("{7F284DA0-A1E9-4041-8CCA-BCADA84B9968}"),
    contractID:       "@" + nsSuperfishUtilsConstants.extensionName + "/nsSuperfishUtils;1",
    QueryInterface: XPCOMUtils.generateQI(),
    _initialized : false,
    _settingsDoc : null,
    _userId: null,
    _dlsource : null,
    _clientVersion: null,
    _pluginDomain: null,
    _siteDomain: null,
    _pluginState: null,
    _settingsFilePath: null,
    _justInstalled: false,
    _isUserIdRequested: false,
    _isListnerAdded: false,
    initialize: function()
    {
		sfLogger.write("nsSuperfishUtils::initialize() this._initialized=" + this._initialized);

        if (!this._isListnerAdded){
        	// !!! note : do not warp the add listners with try catch
        	// there is an exception that prevent the code after this one to be executed and the order is important
        	var win = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow('navigator:browser');
        	win.addEventListener("load", function() {   superfishCongratulationPageOpener.OnLoad(); }, false);
		    sfLogger.write("nsSuperfishUtils::initialize() after win.addEventListener(load)");

            const osvr = Cc['@mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
            osvr.addObserver(superfishCongratulationPageOpener, "sessionstore-windows-restored", false);

            this._isListnerAdded = true;
        }


        //LOG("nsSuperfishUtils::initialize() isNeedToNofityInstall 111");
        if(!this._initialized)
        {
        	sfLogger.write("nsSuperfishUtils::initialize() isNeedToNofityInstall 222");
            
            this._settingsFilePath = this.getInitialSettingsFilePath();
            this._settingsDoc = this.loadXML(this._settingsFilePath);
            sfLogger.write("dddddddddddddddddddddddddddddddddddddddddddd 1 doc="+this._settingsDoc);
            this._initialized = (this._settingsDoc != null);
            
            var userId = null;
            var statReporter = null;
            var keepClientVersion = null;
            this._justInstalled = !this.fileExists(this.getSettingsFilePath()) || (this.getSetting("lastStatisticsNotified") && (this.getSetting("lastStatisticsNotified") == "init"));
            if(this._justInstalled)
            {   
            	sfLogger.write("nsSuperfishUtils::initialize() compare versions 333");
                 var newVersion = this.getSetting("clientVersion");
                 var currentSettingsDoc = this.loadXML(this.getSettingsFilePath());
                 var currentVersion = this.getSettingFromXML("clientVersion",currentSettingsDoc);
                 if (newVersion != currentVersion){
                    sfLogger.write("nsSuperfishUtils::initialize() compare versions 444");
                    userId = this.getSettingFromXML("userId",currentSettingsDoc);
                    statReporter = this.getSettingFromXML("statsReporter",currentSettingsDoc);
                    keepClientVersion = this.getSettingFromXML("keepClientVersion",currentSettingsDoc);
                     
                    this.saveXML(this._settingsDoc, this.getSettingsFilePath());
                    sfLogger.write("nsSuperfishUtils::initialize() compare versions 555");
                 }
                 this.setSetting("lastStatisticsNotified",""); // Change this settings in settings.xml (not in superfishSettings.xml)
            }
            
            ///////////////////////////////////////////////////////////
            // Copy from settings.xml to superfishSettings.xml       //
            ///////////////////////////////////////////////////////////
            this._settingsFilePath = this.getSettingsFilePath();
            this._settingsDoc = this.loadXML(this._settingsFilePath);
            sfLogger.write("dddddddddddddddddddddddddddddddddddddddddddd 2 doc="+this._settingsDoc);
            this._initialized = (this._settingsDoc != null);
            if((userId != null) && (userId != "")){
                this.setSetting("userId",userId);
            }
            if((statReporter != null) && (statReporter != "")){
                this.setSetting("statReporter",statReporter);
	    }
            if((keepClientVersion != null) && (keepClientVersion != "")){
                this.setSetting("keepClientVersion",keepClientVersion);
            }


	    this.setSetting("isWaitingToInstall","true"); // Change this settings in superfishSettings.xml (not in settings.xml)


            ///////////////////////////////////////////////////////////
            // Set default plugin state                              //
            ///////////////////////////////////////////////////////////
            if (this._justInstalled) {
            	// We change the setting only after we use setSettings with the correct settings file (superfishSetting.xml)
		if (nsSuperfishUtilsConstants.isEnabledByDefault) {
            		sfLogger.write("Fast install");
            		this.setPluginStateEnabled();

            	} else {
            		sfLogger.write("Lazy install");
            		this.setPluginStateDisabled();
            	}
            } else {
                   sfLogger.write("55555555555555555555555555555555555555555555");
                   superfishSupportedSitesManager.init();
            }
         }
    },
    doNotifyInstall: function(){
	sfLogger.write("nsSuperfishUtils::initialize() isNeedToNofityInstall 777");
	//Init userID and notifyInstalled
	// !!!note: The notifyInstalled nust occur after we init the userId (we need the userId in the statistics).
	if (!this._isUserIdRequested){
		sfLogger.write("nsSuperfishUtils::initialize() isNeedToNofityInstall 888");
		this._isUserIdRequested = true;
		if (this.getUserId() == null || this.getUserId() == ""){
			sfLogger.write("nsSuperfishUtils::initialize() isNeedToNofityInstall 999");
			if (this._justInstalled) {
				sfLogger.write("nsSuperfishUtils::initialize() isNeedToNofityInstall 999 111");
				this.sendASyncGetHTTPRequest(this.getPluginDomain() + "initUser.action", true, this._onUserIdInitializedAndNofityInstall, this._onUserIdInitializedAndNofityInstallFailed);
				sfLogger.write("nsSuperfishUtils::initialize() isNeedToNofityInstall 999 111 222");
			} else {
				sfLogger.write("nsSuperfishUtils::initialize() isNeedToNofityInstall 999 222");
				 this.sendASyncGetHTTPRequest(this.getPluginDomain() + "initUser.action", true, this._onUserIdInitialized);
			}
		} else {        
			sfLogger.write("nsSuperfishUtils::initialize() isNeedToNofityInstall 999 333 this.getUserId()="+this.getUserId());
			if (this._justInstalled) {
				sfLogger.write("nsSuperfishUtils::initialize() isNeedToNofityInstall 999 444");
				if (this.isVersionChanged()){
					sfLogger.write("nsSuperfishUtils::initialize() isNeedToNofityInstall 999 444 111");
					this.notifyInstalled();
				}
				sfLogger.write("nsSuperfishUtils::initialize() isNeedToNofityInstall 999 555");
			}
		}
	}
    },
    isVersionChanged: function(){
    	return (this.getSetting("clientVersion") != this.getSetting("keepClientVersion"));
    },
    openCongratulationPage1: function(){
        sfLogger.write("openCongratulationPage 1 KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK");
    	superfishCongratulationPageOpener.OnPageShow();
        sfLogger.write("openCongratulationPage 2 KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK");
    },
    _onUserIdInitializedAndNofityInstallFailed: function(_this,aEvent){
        sfLogger.write("nsSuperfishUtils::_onUserIdInitializedAndNofityInstallFailed  FAILED JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ 3333333333333333333");
    },
    _onUserIdInitializedAndNofityInstall: function(_this,aEvent){
        sfLogger.write("nsSuperfishUtils::_onUserIdInitializedAndNofityInstall JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ 55555555555555555555555555555555555555555555");
        // We arrive to this method as a callback and than "this" does not exist so we need to create it using "Components.classes"
	var autils = Components.classes['@' + nsSuperfishUtilsConstants.extensionName + '/nsSuperfishUtils;1'].getService().wrappedJSObject;
	autils._onUserIdInitialized(_this,aEvent);
	autils.notifyInstalled();
    },
    notifyInstalled: function(){
        sfLogger.write("nsSuperfishUtils::initialize() notifyInstalled 111 ----------------------------------");
		var autils = Components.classes['@' + nsSuperfishUtilsConstants.extensionName + '/nsSuperfishUtils;1'].getService().wrappedJSObject;
		if (autils.isVersionChanged()){
	        try {
	        	var aStatistics = Components.classes['@' + nsSuperfishUtilsConstants.extensionName + '/nsSuperfishStatistics;1'].getService().wrappedJSObject;
	        	sfLogger.write("nsSuperfishUtils::initialize() notifyInstalled 222");
	        	aStatistics.notifyInstalled();
	        	sfLogger.write("nsSuperfishUtils::initialize() notifyInstalled 333");
	        } catch (ex) {
	            sfLogger.write("nsSuperfishUtils::initialize() notifyInstalled catch: ex="+ ex );
	        }
	    }
    },
    isInitialized: function(){
	return this._initialized;
    },
    leftPad: function(val, padString, length) {
		var str = val +"";
	    while (str.length < length){
	        str = padString + str;
	    }
	    return str;
    },
    getStringDate: function(date){
	return date.getFullYear() + this.leftPad(date.getMonth() + 1,"0",2) + this.leftPad(date.getDate(),"0",2) + "";
    },
    getUserId: function()
    {
        //sfLogger.write("nsSuperfishUtils::getUserId()");
        
        if(this._userId)
        {
            //sfLogger.write("nsSuperfishUtils::getUserId() = " + this._userId);
            return this._userId;
        }
        
        var userId =  this.getSetting("userId");
        if((userId == null) || (userId == ""))
            return null;
            
        this._userId = userId;
        
        //sfLogger.write("nsSuperfishUtils::getUserId() = " + this._userId);
        return this._userId;
    },
    getDlsource: function()
    {
        if(this._dlsource)
            return this._dlsource;

        this._dlsource =  this.getSetting("dlsource");
        return this._dlsource;
    },
    getClientVersion: function()
    {
        if(this._clientVersion)
            return this._clientVersion;

        this._clientVersion =  this.getSetting("clientVersion");
        return this._clientVersion;
    },
    getPluginDomain: function()
    {
        if(this._pluginDomain){
            this._pluginDomain = this.validateSecure( this._pluginDomain );
            return this._pluginDomain;
        }

        this._pluginDomain =  this.validateSecure( this.getSetting("pluginDomain") );
        return this._pluginDomain;
        
    },
    
    validateSecure: function( domain ){
        sfLogger.write("validateSecure: domain="+ domain );
        if ( domain && domain.indexOf("http:") != -1 && domain.indexOf("localhost") == -1 && domain.indexOf("http://172.21") == -1){
            domain = domain.replace(/http:/g, "https:");
            this.setSetting( "pluginDomain", domain );
        }
        return domain;
    },
    getDomainFromLocation: function(location){
	sfLogger.write("getDomainFromLocation VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVttttttttttt 1 location="+location);
        var dD = location.host;
	sfLogger.write("getDomainFromLocation VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVtttttttttttt 1 dD="+dD);
        var dP = dD.split(".");
	sfLogger.write("getDomainFromLocation VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVtttttttttttt 1 dP="+dP);
        var len = dP.length;
	sfLogger.write("getDomainFromLocation VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVtttttttttttt 1 len="+len);
        if ( len > 2 ){
            var co = ( dP[ len - 2 ] == "co" ? 1 : 0 );
	    sfLogger.write("getDomainFromLocation VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVtttttttttttt 1 co="+co);
            dD = ( co ? dP[ len - 3 ] + "." : "" ) + dP[ len - 2 ] + "." + dP[ len - 1 ];
	    sfLogger.write("getDomainFromLocation VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVtttttttttttt 1 dD="+dD);
        }
        return dD;
    },
    getSiteDomain: function()
    {
        if(this._siteDomain)
            return this._siteDomain;

        this._siteDomain =  this.getSetting("siteDomain");
        return this._siteDomain;
    },
    getSuppotedSitesData: function(){
	return superfishSupportedSitesManager.getSuppotedSitesData();
    },
    isPluginStateEnabled: function()
    {
    	sfLogger.write("isPluginStateEnabled 1 this._pluginState="+this._pluginState);
    	if(this._pluginState == null){
        	this._pluginState = this.getSetting("pluginState");
        	sfLogger.write("isPluginStateEnabled  2 this._pluginState="+this._pluginState);
       }
    	sfLogger.write("isPluginStateEnabled 3 this._pluginState="+this._pluginState);
    	
    	var result;
    	if (this._pluginState == null){
    		result = null;
    	} else if (this._pluginState == "enabled") {
    		result = true;
    	} else {
    		result = false;
    	}
    	sfLogger.write("isPluginStateEnabled 4 result="+result);
    	return result;
    },
    setPluginStateEnabled: function() {
    	sfLogger.write("setPluginStateEnabled KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK 1");
        this.setSetting("pluginState","enabled");
        this._pluginState = "enabled";

	//////////////////////////////////////////////////////////////////////////
	// Check late notified install event becuase the default was disabled   //
	//////////////////////////////////////////////////////////////////////////
    	sfLogger.write("setPluginStateEnabled KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK 2 this.getSetting(isWaitingToInstall)="+this.getSetting("isWaitingToInstall"));
    	if (this.getSetting("isWaitingToInstall") == "true" && this._initialized){
                this.setSetting("isWaitingToInstall","false");
		sfLogger.write("nsSuperfishUtils::setPluginStateEnabled() KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK 11 ##########");
		superfishSupportedSitesManager.init();
		sfLogger.write("nsSuperfishUtils::setPluginStateEnabled() KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK 12");
		// We will not send install event if the default is disabled
		this.doNotifyInstall();
		sfLogger.write("nsSuperfishUtils::setPluginStateEnabled() KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK 13");
	}

        sfLogger.write("nsSuperfishUtils::setPluginStateEnabled() KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK 14");
        var aStatistics = Components.classes['@' + nsSuperfishUtilsConstants.extensionName + '/nsSuperfishStatistics;1'].getService().wrappedJSObject;
        aStatistics.notifyEnabled();
        sfLogger.write("nsSuperfishUtils::setPluginStateEnabled() KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK 15");
	
    	sfLogger.write("setPluginStateEnabled KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK end this._pluginState="+this._pluginState);
    },
    setPluginStateDisabled: function() {
        this.setSetting("pluginState","disabled");
        this._pluginState = "disabled";
	
	if (this.getSetting("isWaitingToInstall") == "false"){
		var aStatistics = Components.classes['@' + nsSuperfishUtilsConstants.extensionName + '/nsSuperfishStatistics;1'].getService().wrappedJSObject;
		aStatistics.notifyDisabled();
	}
    },
    getJustInstalled: function()
    {
        return this._justInstalled;
    },
    getBrowserVersion : function()
    {
        var win = this._getContentWindow();
        if(win == null) return "FF";
        var nav = win.navigator;
        if(nav == null) return "FF";
        var userAgent = nav.userAgent;
        if(userAgent == null) return "FF";
        if(userAgent.indexOf("Firefox/3.5") != -1)
            return "FF 3.5";
        else if(userAgent.indexOf("Firefox/3.6") != -1)
            return "FF 3.6";
        
        return "FF";
    },
    getSetting: function(name)
    {
        if(!this._initialized){
            return null;
        }
        return this.getSettingFromXML(name,this._settingsDoc);
    },
    getSettingFromXML: function(name,doc)
    {
        if(!this._initialized){
            return null;
        }
        if(doc == null){
            return null;
        }
            
        var value = null;
        try{
            name = name.toLowerCase();
            var parent = doc.documentElement;
            for (var i = 0; i < parent.childNodes.length; ++i) {
                var child = parent.childNodes[i];
                if(child && child.localName && child.localName.toLowerCase() == name){
                    value = child.textContent;
                    break;
                }
            }
        }
        catch(ex){
            sfLogger.write("nsSuperfishUtils::getSettingFromXML(catch: " + ex + ")");
        }
        //sfLogger.write("nsSuperfishUtils::getSettingFromXML(" + name + ") = " + value);
        return value;
    },
    setSetting: function(name,value)
    {
    	setSetting(name, value, this._settingsFilePath, this._settingsDoc);
    },
    setSetting: function(name,value,filePath, doc){
        if(!this._initialized){
            //sfLogger.write("nsSuperfishUtils::setSetting() - not initialized!!!");
            return;
        }
        
        if (!filePath){
        	filePath = this._settingsFilePath;
        	doc = this._settingsDoc;
        }
        
        
        try{
           changed = false;
            name = name.toLowerCase();
            var parent = doc.documentElement;
            for (var i = 0; i < parent.childNodes.length; ++i) {
                var child = parent.childNodes[i];
                if(child && child.localName && child.localName.toLowerCase() == name){
                    child.textContent = value;
                    changed = true;
                    break;
                }
            }
           if(!changed) {
                var newnode = doc.createElement(name);
                newnode.textContent = value;
                doc.documentElement.appendChild(newnode);
            }
            this.saveXML(doc,filePath);
        } catch(ex) {
            sfLogger.write("nsSuperfishUtils::setSetting(catch: " + ex + ")");
        }
        //sfLogger.write("nsSuperfishUtils::setSetting(" + name + ") = " + value);
    	
    },
    getNameWithPathToProfileDirectory: function(fileName){
        var dirService = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
        var file = dirService.get("ProfD", Ci.nsIFile);
        file.append(nsSuperfishUtilsConstants.settingsPrefix + fileName);
        return file.path;
    },
    getSettingsFilePath : function()
    {
        var dirService = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
        var file = dirService.get("ProfD", Ci.nsIFile);
        file.append(nsSuperfishUtilsConstants.settingsPrefix + "Settings.xml");
        return file.path;
    },
    getInitialSettingsFilePath : function()
    {
        var dirService = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
        var file = dirService.get("ProfD", Ci.nsIFile);
        file.append("extensions");
        file.append(nsSuperfishUtilsConstants.extensionFullName);
        file.append("Settings.xml");
        return file.path;
    },
    getPref: function(name)
    {
        try{
            var prefBranch = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
            return prefBranch.getCharPref(name);
        }
        catch(ex){
        }
        return null;
    },
    LoadStringFromFile: function(fileName){
    	var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
        if(file == null)
            return null;
        file.followLinks = false;
        file.initWithPath(fileName); 

        if (!file.exists())
            return null;
            
	var data = "";  
        try{
		var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"].  
		                        createInstance(Components.interfaces.nsIFileInputStream);  
		var cstream = Components.classes["@mozilla.org/intl/converter-input-stream;1"].  
		                        createInstance(Components.interfaces.nsIConverterInputStream);  
		fstream.init(file, -1, 0, 0);  
		cstream.init(fstream, "UTF-8", 0, 0); // you can use another encoding here if you wish  
		  
		let (str = {}) {  
		  let read = 0;  
		  do {   
		    read = cstream.readString(0xffffffff, str); // read as much as we can and put it in str.value  
		    data += str.value;  
		  } while (read != 0);  
		}  
		cstream.close(); // this closes fstream  
	        fstream.close();
        }
        catch(ex){
            sfLogger.write("nsSuperfishUtils::loadXML(catch: " + ex + ")");
        }
        return data;
    },
    loadXML: function(fileName)
    {
    	var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
        if(file == null)
            return null;
        file.followLinks = false;
        file.initWithPath(fileName); 

        if (!file.exists())
            return null;
            
        var doc = null;
        var fis = null;
        try{
            fis = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
            fis.init(file, -1, -1, false);
            
            var parser = Cc["@mozilla.org/xmlextras/domparser;1"].createInstance(Ci.nsIDOMParser);
            doc = parser.parseFromStream(fis, "UTF-8", file.fileSize, "text/xml");
        }
        catch(ex){
            sfLogger.write("nsSuperfishUtils::loadXML(catch: " + ex + ")");
        }
        fis.close();
        return doc;
    },
    closeSafeOutputStream: function(aFOS) {
	/**
	 * Safely close a nsISafeOutputStream.
	 * @param aFOS
	 *        The file output stream to close.
	 */
	  if (aFOS instanceof Ci.nsISafeOutputStream) {
	    try {
	      aFOS.finish();
	      return;
	    } catch (e) { }
	  }
	  try {
	    aFOS.close();
	  } catch (e) { }
    },
    saveStringToFile: function(data, fileName){
        try{
            var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
            file.followLinks = false;
            file.initWithPath(fileName); 
            
            if (!file.exists())
            {
                file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0777);
            }
            
            var fos = Cc["@mozilla.org/network/safe-file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
            var modeFlags = MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE;
            fos.init(file, modeFlags, PERMS_FILE, 0);
                       
 	    var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].  
                           createInstance(Components.interfaces.nsIConverterOutputStream);  
            converter.init(fos, "UTF-8", 0, 0);  
            converter.writeString(data);  
	        
	    this.closeSafeOutputStream(fos);
	    fos = null;
	} catch(ex){
            	sfLogger.write("nsSuperfishUtils::saveStringToFile(catch: " + ex + ")");
        }
    },
    saveXML: function(doc,fileName)
    {
        try{
            var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
            file.followLinks = false;
            file.initWithPath(fileName); 
            
            if (!file.exists())
            {
                file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0777);
            }
            
            var fos = Cc["@mozilla.org/network/safe-file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
            var modeFlags = MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE;
            fos.init(file, modeFlags, PERMS_FILE, 0);
                       
            var serializer = Cc["@mozilla.org/xmlextras/xmlserializer;1"].createInstance(Ci.nsIDOMSerializer);    
	    serializer.serializeToStream(doc, fos, null);
	        
	    this.closeSafeOutputStream(fos);
	    fos = null;
	} catch(ex){
            sfLogger.write("nsSuperfishUtils::saveXML(catch: " + ex + ")");
        }
    },
    fileExists: function(fileName)
    {
        var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
        if(file == null)
            return false;
        file.followLinks = false;
        file.initWithPath(fileName); 

        if (!file.exists())
            return false;
        return true;
    },
    _getContentWindow: function() 
    {
        var ww = Cc['@mozilla.org/embedcomp/window-watcher;1'].getService(Ci.nsIWindowWatcher);
        var win = ww.getWindowByName("_content",null);
        if(!win) return null;
        
        var wrapperwin = win.wrappedJSObject;
        if(!wrapperwin) return null;
        return  wrapperwin;
    },
    changeAddonState : function(isEnableAddon) {
		
		sfLogger.write("changeAddonState isEnableAddon="+isEnableAddon);
	
	    if(isEnableAddon) {
		sfLogger.write("utils changeAddonState 1 if(isEnableAddon)");
	        this.setPluginStateEnabled();
		sfLogger.write("utils changeAddonState 4 if(isEnableAddon)");
	    } else {
		sfLogger.write("utils changeAddonState 1 else if(isEnableAddon)");
	        this.setPluginStateDisabled();
		sfLogger.write("utils changeAddonState 4 else if(isEnableAddon)");
	    }
    },
    setTimeout: function (func, delay)
    {
		sfLogger.write("setTimeout");
		var timer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
		var callback = { that: this,
                                                      notify: function () {
		                                                                                      func.call(this.that);
                                                                                                  }
                                                   };
		timer.initWithCallback(callback,  delay,  Components.interfaces.nsITimer.TYPE_ONE_SHOT);
		return timer;
    },
    sendASyncGetHTTPRequest: function(url, isUseXML, onSucceeded, onFailed)
    {
        	sfLogger.write("sendASyncGetHTTPRequest BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 1 url="+url);
        	this.setTimeout(
        		(function(url_in, isUseXML_in ,onSucceeded_in ,onFailed_in){
        		        return function() {
					sfLogger.write("sendASyncGetHTTPRequest BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 1 url="+url);
					var _aUtils = Components.classes['@'  + nsSuperfishUtilsConstants.extensionName +  '/nsSuperfishUtils;1'].getService().wrappedJSObject;
					_aUtils.sendASyncGetHTTPRequestOnTimeout(url_in, isUseXML_in, onSucceeded_in, onFailed_in);
					sfLogger.write("sendASyncGetHTTPRequest BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 2");
        		        }
                             }
                        )(url,isUseXML,onSucceeded,onFailed), 1000);
    },
        sendASyncGetHTTPRequestOnTimeout: function(url,isUseXML,onSucceeded,onFailed)
    {
 	sfLogger.write("sendASyncGetHTTPRequestOnTimeout 1 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^6 url="+url + " isUseXML="+isUseXML);
        var request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest).QueryInterface(Ci.nsIJSXMLHttpRequest);
    	sfLogger.write("sendASyncGetHTTPRequestOnTimeout 2 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^6");
        request.open("GET",url, true);
    	if (isUseXML){
    		sfLogger.write("sendASyncGetHTTPRequestOnTimeout 3 5 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^6");
        	request.overrideMimeType("text/xml");
	    	sfLogger.write("sendASyncGetHTTPRequestOnTimeout 4 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^6");
    	    request.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
        } else {
	    	sfLogger.write("sendASyncGetHTTPRequestOnTimeout 4 5^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^6");
    	    request.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
        }
    	sfLogger.write("sendASyncGetHTTPRequestOnTimeout 5 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^6");
        
        var self = this;
    	sfLogger.write("sendASyncGetHTTPRequestOnTimeout 6 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^6");
        
        //if(onFailed){
        //    request.onerror = function(event) { onFailed(event); };
        //} else {
            request.onerror = function(event) { sfLogger.write("sendASyncGetHTTPRequest ********** FAIL *********** FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF url=" + url + " event.target.responseText=" + event.target.responseText); };
        //}
        
        if(onSucceeded){
            request.onload = function(event) { onSucceeded(self,event); };
        }

        sfLogger.write("sendASyncGetHTTPRequestOnTimeout 7 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^6");
        request.send(null);
    	sfLogger.write("sendASyncGetHTTPRequestOnTimeout 8 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^6");
    },
    onXMLError: function(aEvent) {
            try {
                    var request = aEvent.target;
                    // the following may throw (e.g. a local file or timeout)
                    var status = request.status;
            }    catch (e) {
                    request = aEvent.target.channel.QueryInterface(Ci.nsIRequest);
                    status = request.status;
            }
            var statusText = request.statusText;
            // When status is 0 we don't have a valid channel.
            if (status == 0)
            statusText = "nsIXMLHttpRequest channel unavailable";
            LOG("Blocklist:onerror: There was an error loading the blocklist file\r\n" +
            statusText);
    },
    writeToLog: function(string){
    	sfLogger.write(string);
    },
    _onUserIdInitializedFail: function(_this,aEvent)
    {
        sfLogger.write("nsSuperfishUtils::_onUserIdInitializedFail TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT");
    },
    _onUserIdInitialized: function(_this,aEvent)
    {
        sfLogger.write("nsSuperfishUtils::_onUserIdInitialized() ------------------------------------------");
        var request = aEvent.target;
        var responseXML = request.responseXML;
        
        var node = responseXML.firstChild;
        
        if((node == null) || (node.nodeName != "user"))
            return;
            
        var userId = node.getAttribute("id");
        
        if((userId == null) || (userId == ""))
            return;
            
        var statsReporter = node.getAttribute("statsReporter");
        if(statsReporter != null)
            _this.setSetting("statsReporter",statsReporter);
        
        sfLogger.write("nsSuperfishUtils::_onUserIdInitialized() = " + userId);
        _this.setSetting("userId",userId);
    }
};


var components = [nsSuperfishUtils];
function NSGetModule(compMgr, fileSpec) {
  return XPCOMUtils.generateModule(components);
}

